package com.hm.hall.user.service;

import com.hm.hall.commons.constans.ErrorCode;
import com.hm.hall.commons.constans.GameConstans;
import com.hm.hall.commons.constans.RedisKeysDefine;
import com.hm.hall.commons.constans.ValueConstants;
import com.hm.hall.commons.dao.MobileSessionMapper;
import com.hm.hall.commons.dao.UserMapper;
import com.hm.hall.commons.domain.MobileSession;
import com.hm.hall.commons.domain.User;
import com.hm.hall.commons.service.RedisCacheService;
import com.hm.hall.commons.service.helper.SessionServiceHelper;
import com.hm.hall.commons.util.*;
import com.hm.hall.user.UserConstants;
import com.hm.hall.user.controller.po.SimpUserPO;
import com.hm.hall.user.controller.req.EmailLoginReq;
import com.hm.hall.user.controller.req.EmailRegReq;
import com.hm.hall.user.controller.req.ThirdLoginReq;
import com.hm.hall.user.controller.resp.LoginResp;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Calendar;
import java.util.Date;

@Service
public class UserLoginService {
    private static Logger log = Logger.getLogger(UserLoginService.class);
    @Autowired
    private static UserService userService;
    @Autowired
    private MobileSessionMapper mobileSessionMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private UserLoginLogService userLoginLogService;

    public static LoginResp getThirdLoginRespBySession() {
        LoginResp resp = (LoginResp) ActionUtils.getSession().getAttribute(SessionServiceHelper.USER_LOGIN_RESP);
        if (resp == null) {
            return null;
        }
        long now = System.currentTimeMillis();
        // 每隔 一段时间同步一下用户的最新资料
        if (now - resp.getLastGetLoginRespTime() > 3000) {
            User u = userService.getUserDOByUserId(resp.getUser().userId);
            if (u == null) {
                return new LoginResp(ErrorCode.blacklist_content);
            }
            BeanUtils.copyProperties(u, resp.getUser());

            setThirdLoginRespToSession(resp);
        }
        resp.setLastGetLoginRespTime(now);
        return resp;
    }

    public static void setThirdLoginRespToSession(LoginResp resp) {
        try {// websocket 无法获取session
            HttpSession session = ActionUtils.getSession();
            session.setAttribute(SessionServiceHelper.USER_LOGIN_RESP, resp);
            session.setAttribute(SessionServiceHelper.USER_LOGIN_RESP_JSON, JsonUtils.toJSONString(resp));
        } catch (Exception e) {
            log.error("无法获取session");
        }
    }

    /**
     * 生成登录 加密方式为：md5(user+game+channel+time+LOGINKEY)`LOGINKEY
     */
    public String generateLoginToken(ThirdLoginReq req) {
        return Md5Salt.toMD5(req.username + req.time);
    }

    /**
     * 第三方账号登录
     *
     * @param req 第三方登录参数
     * @return LoginResp
     */
    public LoginResp thirdLogin(ThirdLoginReq req) {
        // 参数验证
        if (StringUtils.isBlank(req.username) || req.getUnionid().equals("undefined")) {
            return new LoginResp(ErrorCode.parament_error.code, "用户标示不能为空");
        }
        if (req.getUnionid().equals("null")) {
            return new LoginResp(ErrorCode.user_error_login);
        }
        if (req.time == 0) {
            return new LoginResp(ErrorCode.parament_error.code, "时间戳不能为空");
        }
        // 登录CD 同步模块
        boolean isCD = redisCacheService.isCD("CD_THIRD_LOGIN_" + req.username, 5,
                SyncUtils.getLockObject("CD_THIRD_LOGIN_" + req.username));
        if (isCD) {
            return new LoginResp(ErrorCode.call_cd_error.code, "登录速度过快，请稍候再试");
        }
        log.info(" 用户进行登录 " + req.getNickname());
        // 2 首次登录创建用户
        User user = userService.getUserByChanelAndUserNameByAllStatus(req.username, req.getUnionid());
        if (user != null && user.getActiveState() != 0) {
            return new LoginResp(ErrorCode.blacklist_content);
        }

        if (user == null) {
            String avatar = StringUtils.isEmpty(req.avatar) ? GameConstans.DEFAULT_AVATAR : req.avatar;
            if (avatar.equals("undefined")) {
                avatar = GameConstans.DEFAULT_AVATAR;
            }
            if (!avatar.contains("hall")) {
                avatar = OssUtils.uploadwx2oss(avatar);
            }
            req.nickname = StringUtils.isBlank(req.nickname) ? "" : req.nickname;
            user = new User();
            user.setUsername(req.username);
            user.setSex(req.sex);
            user.setAvatar(avatar);
            user.setNickname(req.nickname);
            user.setActiveState(new Integer(GameConstans.USER_STATE_OK));
            user.setRegTime(new Date());
            user.setGameChannel(req.getChannel());
            user.setUserLang(req.getLang());
            user.setDiamondNum(ValueConstants.DEFAULT_ZERO);
            user.setDeviceType(req.getDeviceType());
            user.setUnionid(req.getUnionid());
            user.setOpenId(req.getUsername());
            String location = IPUtil.getLocationByIp(IPUtil.getIpAddr());
            String[] arry = location.split(" ");
            if (arry.length == 2) {
                user.setCountry(arry[0]);
                user.setCity(arry[1]);
            }
            userMapper.insertSelectiveGetKey(user);
            // 空昵称 ,默认游客昵称 [游客]+userId
        } else {
            String avatar = StringUtils.isEmpty(req.avatar) ? user.getAvatar() : req.avatar;
            if (avatar.equals("undefined")) {
                avatar = GameConstans.DEFAULT_AVATAR;
            }
            if (!avatar.contains("hall")) {
                if (!redisCacheService.isCD("uploadAvatar-" + user.getUserId(), 3600 * 24) && !req.channel.contains("line") && !req.channel.contains("faceBook")) {
                    avatar = OssUtils.uploadwx2oss(avatar);
                } else {
                    avatar = user.getAvatar();
                }
            }
            userService.upLocation(user, IPUtil.getIpAddr());

            // 昵称 和 头像 性别 变动的话同步到数据库
            if ((req.nickname != null && !req.nickname.equals(user.getNickname()))
                    || (req.avatar != null && !avatar.equals(user.getAvatar()))
                    || (req.unionid != null && !req.unionid.equals(user.getUnionid()))
                    || (req.username != null && !req.username.equals(user.getOpenId()))
                    || (req.sex != null && req.sex != user.getSex())
                    || (req.deviceType != null && req.deviceType != user.getDeviceType())
                    || (req.lang != null && !req.lang.equals(user.getUserLang()))) {
                User upUser = new User();
                upUser.setUserId(user.getUserId());
                upUser.setAvatar(avatar);
                upUser.setSex(req.sex);
                upUser.setNickname(StringUtils.isBlank(req.nickname) ? user.getNickname() : req.nickname);
                upUser.setUserLang(req.lang);
                upUser.setDeviceType(req.getDeviceType());
                upUser.setUnionid(req.getUnionid());
                upUser.setOpenId(req.getUsername());
                BeanUtils.copyProperties(upUser, user);
                userMapper.updateByPrimaryKeySelective(upUser);
                if (!StringUtils.isBlank(req.nickname) && !req.nickname.equals(user.getNickname())) {
                    userService.afterChangeName(user.getUserId(), user.getNickname(), upUser.getNickname());
                }
            }
        }
        LoginResp resp = sendSession(user);
        // 添加用户登录日志
        try {
            addUserLoginLog(user);
        } catch (Exception e) {
        }
        return resp;
    }

    // 保存会话session
    private LoginResp sendSession(User user) {
        LoginResp resp = new LoginResp();
        resp.user = new SimpUserPO();
        BeanUtils.copyProperties(user, resp.user);
        setCanUpdateUser(user, resp);
        //DealUserBalance balance = dealUserBalanceService.getUserBalanceByUserId(user.getUserId());
        //resp.user.setBalanceDiamond(balance.getBalanceDiamond());
        // 3 派发 sessionToken
        Calendar cal = Calendar.getInstance();
        MobileSession session = new MobileSession();
        session.setUserId(user.getUserId());
        session.setToken(DigestUtils.md5DigestAsHex(String.valueOf(cal.getTimeInMillis()).getBytes())); // md5当前时间戳
        session.setTimestamp(cal.getTime());
        cal.add(Calendar.DATE, 30);
        session.setFailureTime(cal.getTime());

        int resCount = mobileSessionMapper.updateByPrimaryKey(session);
        if (resCount == 0) {
            mobileSessionMapper.insert(session);
        }

        resp.sessionToken = session.getToken();
        resp.timestamp_L = session.getTimestamp().getTime();
        resp.failureTime_L = session.getFailureTime().getTime();

        String key = RedisKeysDefine.SESSIONTOKEN.replace("${userId}", "" + user.getUserId());
        redisCacheService.setex(key, GameConstans.SESSIONTOKEN_EXP, JsonUtils.toJSONString(session));

        log.info(user.getNickname() + " 用户登录成功 " + user.getUsername() + "; 派发sessionToken : " + session.getToken());
        UserLoginService.setThirdLoginRespToSession(resp);
        return resp;
    }

    public LoginResp emailRegistration(EmailRegReq req) {
        // 参数验证
        if (StringUtils.isBlank(req.email)) {
            return new LoginResp(ErrorCode.parament_error.code, "用户标示不能为空");
        }
        if (req.time == 0) {
            return new LoginResp(ErrorCode.parament_error.code, "时间戳不能为空");
        }
        if (!req.getPassword().equals(req.getPasswordRe())) {
            return new LoginResp(ErrorCode.parament_error.code, "两次密码不一致");
        }

        // 检查用户是否存在
        User user = userService.getUserByEmailByAllStatus(req.email);
        if (user != null) {
            return new LoginResp(ErrorCode.exist_email);
        }
        // 登录CD 5秒钟
        boolean isCD = redisCacheService.isCD("CD_THIRD_LOGIN_" + req.email, 5,
                SyncUtils.getLockObject("CD_THIRD_LOGIN_" + req.email));
        if (isCD) {
            return new LoginResp(ErrorCode.call_cd_error.code, "登录速度过快，请稍候再试");
        }
        log.info("用户邮箱注册" + req.getNickname());
        String avatar = StringUtils.isEmpty(req.avatar) ? GameConstans.DEFAULT_AVATAR : req.avatar;

        req.nickname = StringUtils.isBlank(req.nickname) ? "" : req.nickname;
        user = setUserCommonInfo(req, avatar);
        String channel = UserConstants.GAME_CHANNEL_EMAIL_AND;
        if (req.getDeviceType() == GameConstans.DEVICE_TYPE_IOS) {
            channel = UserConstants.GAME_CHANNEL_EMAIL_IOS;
        }
        user.setGameChannel(channel);
        user.setPassword(userService.getMD5Password(req.getPassword()));
        user.setUserLang(req.getLang());
        String location = IPUtil.getLocationByIp(IPUtil.getIpAddr());
        String[] arry = location.split(" ");
        if (arry.length == 2) {
            user.setCountry(arry[0]);
            user.setCity(arry[1]);
        }
        userMapper.insertSelectiveGetKey(user);
        // 空昵称 ,默认游客昵称 [游客]+userId
        LoginResp resp = sendSession(user);
        // 添加用户登录日志
        try {
            addUserLoginLog(user);
        } catch (Exception e) {
        }
        return resp;
    }

    private User setUserCommonInfo(EmailRegReq req, String avatar) {
        User user;
        user = new User();
        user.setEmail(req.email);
        user.setNickname(req.nickname);
        user.setSex(req.sex);
        user.setAvatar(avatar);
        user.setActiveState(new Integer(GameConstans.USER_STATE_OK));
        user.setRegTime(new Date());
        return user;
    }

    private void setCanUpdateUser(User user, LoginResp resp) {
        if (UserConstants.GAME_CHANNEL_VI.equals(user.getGameChannel())
                || UserConstants.GAME_CHANNEL_EMAIL_IOS.equals(user.getGameChannel()) || UserConstants.GAME_CHANNEL_EMAIL_AND.equals(user.getGameChannel())) {
            resp.user.setCanUpdateUserInfo(ValueConstants.YES);
            long countDown = redisCacheService.ttl(RedisKeysDefine.USER_UPDATE_USER_INFO + user.getUserId());
            if (countDown == RedisCacheService.NOT_EXIST) {
                countDown = ValueConstants.DEFAULT_ZERO;
            }
            resp.user.setUpdateUserCountDown(countDown);
        } else {
            resp.user.setCanUpdateUserInfo(ValueConstants.NO);
            resp.user.setUpdateUserCountDown(ValueConstants.NOT_EXIST);
        }
    }

    /**
     * 使用邮箱登录
     *
     * @param req 邮箱登录参数
     * @return LoginResp
     */
    public LoginResp emailLogin(EmailLoginReq req) {
        // 参数验证
        if (StringUtils.isBlank(req.email)) {
            return new LoginResp(ErrorCode.parament_error.code, "邮箱不能为空");
        }
        if (StringUtils.isBlank(req.password)) {
            return new LoginResp(ErrorCode.parament_error.code, "密码不能为空");
        }
        if (req.time == 0) {
            return new LoginResp(ErrorCode.parament_error.code, "时间戳不能为空");
        }

        // 邮箱登录暂定一秒+CD
        boolean isCD = redisCacheService.isCD("CD_THIRD_LOGIN_" + req.email, 1,
                SyncUtils.getLockObject("CD_THIRD_LOGIN_" + req.email));
        if (isCD) {
            return new LoginResp(ErrorCode.call_cd_error.code, "登录速度过快，请稍候再试");
        }

        log.info("用户使用邮箱登录 " + req.getTime());
        // 2 首次登录创建用户
        User user = userService.getUserByEmailByAllStatus(req.email);
        if (user == null || user.getActiveState() != 0
                || !userService.getMD5Password(req.password).equals(user.getPassword())) {
            return new LoginResp(ErrorCode.not_match_password_email);
        }
        userService.upLocation(user, IPUtil.getIpAddr());
        // 昵称 和 头像 性别 变动的话同步到数据库
        if ((req.nickname != null && !req.nickname.equals(user.getNickname()))
                || (req.avatar != null && !req.avatar.equals(user.getAvatar()))
                || (req.sex != null && req.sex != user.getSex())
                || (req.lang != null && !req.lang.equals(user.getUserLang()))
                || (req.deviceType != null && !req.deviceType.equals(user.getDeviceType()))) {
            User upUser = new User();
            upUser.setUserId(user.getUserId());
            upUser.setSex(req.sex);
            upUser.setUserLang(req.lang);
            upUser.setDeviceType(req.deviceType);
            userMapper.updateByPrimaryKeySelective(upUser);
        }

        //邮箱区分 设备
        if ((!UserConstants.GAME_CHANNEL_EMAIL_AND.equals(user.getGameChannel()) && !UserConstants.GAME_CHANNEL_EMAIL_IOS.equals(user.getGameChannel()))) {
            User upUser = new User();
            upUser.setUserId(user.getUserId());
            String channel = UserConstants.GAME_CHANNEL_EMAIL_AND;
            if (req.getDeviceType() == GameConstans.DEVICE_TYPE_IOS) {
                channel = UserConstants.GAME_CHANNEL_EMAIL_IOS;
            }
            upUser.setGameChannel(channel);
            user.setGameChannel(channel);
            userMapper.updateByPrimaryKeySelective(upUser);
        }

        LoginResp resp = sendSession(user);
        // 添加用户登录日志
        try {
            addUserLoginLog(user);
        } catch (Exception e) {
        }
        return resp;
    }

    /**
     * 检测用户是否登录
     */
    public boolean checkUserIsLogin(HttpServletRequest request) {
        LoginResp loginResp = UserLoginService.getThirdLoginRespBySession();
        if (loginResp != null && loginResp.ok()
                && userService.veryfiySessionToken(loginResp.user.userId, loginResp.sessionToken).ok()) {
            return true;
        }
        return false;
    }

    // 添加用户登录日志
    public void addUserLoginLog(User user) {
        // 登录日记
        HttpServletRequest request = ActionUtils.getRequest();
        String headerUserAgent = request.getHeader("User-agent");
        String ipAddr = IPUtil.getIpAddr();
        userLoginLogService.insertUserLoginLog(user, ipAddr, headerUserAgent, ""); // 登录日志

    }

}
